package ee.fujitsu;

import java.util.HashMap;
import java.util.Map;
import java.util.Random;

import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.apache.commons.cli.PosixParser;

import ee.fujitsu.common.Printer;
import ee.fujitsu.entity.Customer;
import ee.fujitsu.entity.JournalRecord;
import ee.fujitsu.entity.Movie;
import ee.fujitsu.entity.state.Store;
import ee.fujitsu.exception.ServiceException;
import ee.fujitsu.handlers.HelpHandler;
import ee.fujitsu.utils.Init;
import ee.fujitsu.utils.Orders;
import ee.fujitsu.utils.TestInitImpl;

/**
 * The Class Main.
 */
public class Main {
	
	  /** The Constant IO_EXCEPTION. */
  	final static int IO_EXCEPTION = 12;
	  
  	/** The Constant FILE_NOT_FOUND. */
  	final static int FILE_NOT_FOUND = 15;
	  
  	/** The Constant NUMBER_FORMAT. */
  	final static int NUMBER_FORMAT = 13;
	  
  	/** The Constant NO_SUCH_ELEMENT. */
  	final static int NO_SUCH_ELEMENT = 14;
	  
  	/** The Constant APP_EXCEPTION. */
  	final static int APP_EXCEPTION = 16;

	/**
	 * The main method.
	 *
	 * @param args the arguments
	 */
	public static void main(String[] args) {
	
        Map<Integer, Customer> customers = null;
        Map<Integer, JournalRecord> journal = null;
        Init init = new TestInitImpl();
        Store store = null;
        try {
	        store = new Store(init.getMovies(), 
	        		new HashMap<Integer, Movie>(), 
	        		new HashMap<Integer, Movie>());
			customers = init.getCustomers();

	        
			journal = init.getJournal(customers, store);
		} catch (ServiceException e1) {
            exceptionOutput(new ServiceException(APP_EXCEPTION, e1.getMessage()));
		}        
        
        final CommandLineParser cmdLinePosixParser = new PosixParser();  
        final Options possibleOptions = constructPossibleOptions();  
        CommandLine commandLine = null; 
        try  
        {   
           commandLine = cmdLinePosixParser.parse(possibleOptions, args);  
        }catch (ParseException parseException)  // checked exception  
        {  
          exceptionOutput(new ServiceException(APP_EXCEPTION, parseException.getMessage()));
        }  
		if (commandLine.hasOption("help"))  {
            HelpHandler handler = new HelpHandler();
            handler.handle();
         } else if (commandLine.hasOption("add"))  {
        	 int filmQty = 0;
			try {
				filmQty = Integer.parseInt(commandLine.getOptionValues("add")[0]);
			} catch (NumberFormatException e1) {
				filmQty = 1 + new Random().nextInt(5);
			}
        	 if (filmQty <= 0) getNumberMessage ();
             int daysQty;
        	 try {
            	daysQty = Integer.parseInt(commandLine.getOptionValues("add")[1]);
			 } catch (ArrayIndexOutOfBoundsException e) {
           	 	daysQty = 1 + new Random().nextInt(2);
			 } catch (NumberFormatException e1) {
				daysQty = 1 + new Random().nextInt(2);
			 }
        	 if (daysQty <= 0) getNumberMessage ();
        	 Orders.addOrder(customers, store, filmQty, daysQty);
         } else if (commandLine.hasOption("late"))  {
        	 int daysQty = 0;
			try {
				daysQty = Integer.parseInt(commandLine.getOptionValue("late"));
			} catch (NumberFormatException e) {
				daysQty = 1 + new Random().nextInt(5);
			}
        	 if (daysQty <= 0) getNumberMessage ();
        	 Orders.lateOrder(journal, store, daysQty);
         } else if (commandLine.hasOption("bonus"))  {
        	 int daysQty;
			try {
				daysQty = Integer.parseInt(commandLine.getOptionValue("bonus"));
			} catch (NumberFormatException e) {
				daysQty = 1 + new Random().nextInt(2);
			}
       	 	if (daysQty <= 0) getNumberMessage ();
        	 Orders.bonusOrder(journal, store, daysQty);
         } else if (commandLine.hasOption("invent"))  {
        	 String type = commandLine.getOptionValue("invent");
        	 if (type.equals("a"))
        		 store.addFilm();
        	 else if (type.equals("d")) {
 				int index =  store.getMovieIndex("Choose  id for delete: ");
        		store.deleteFilm(index);
        	 }
        	 else if (type.equals("c")) {
  				int index =  store.getMovieIndex("Choose  id for change: ");
        		 store.changeFilm(index);
        	 }
           	 else if (type.equals("l"))
          		Printer.print("Films in shop quantity:" + store.countStoreFilms());
           	 else if (type.equals("la"))
   				Printer.print("Total film quantity:" + store.countAllFilms());
           	 else
           		 Printer.print("Cant assept command line argument");
          }
        	 
	}


		/**
		 * Switcher for exception output.
		 * 
		 * Use {@link #exceptionOutput(String)} for output exception
		 *
		 * @param e the e
		 */
        private static void exceptionOutput(ServiceException e) {
           switch (e.getCode()) {
           case IO_EXCEPTION:
              Printer.print("IO exception = " + e.getMessage());
              break;
           case NUMBER_FORMAT:
              Printer.print("Invalid format = " + e.getMessage());
              break;
           case NO_SUCH_ELEMENT:
              Printer.print("No such element in collection :" + e.getMessage());
              break;
           case FILE_NOT_FOUND:
              Printer.print("File not found = " + e.getMessage());
              break;
           case APP_EXCEPTION:
              Printer.print("Application error = " + e.getMessage());
              break;

           default:
              break;
           }
           System.exit(0);
        }


	  /**
  	 * Construct possible options.
  	 *
  	 * @return the options
  	 */
  	private static Options constructPossibleOptions()  
	   {  
	      final Options filmOptions = new Options();  
	      filmOptions.addOption("add", true, "add quantity one customer");  
	      filmOptions.addOption("late", true, "add late day quantity");  
	      filmOptions.addOption("bonus", true, "bonus demonstrate");  
	      filmOptions.addOption("invent", true, "inventure");  
	      filmOptions.addOption("help", false, "help description");  
	      return filmOptions;  
	   } 
	  
	  /**
  	 * Gets the number message.
  	 *
  	 * @return the number message
  	 */
  	private static void getNumberMessage () {
		  exceptionOutput(new ServiceException(APP_EXCEPTION, "Number of argument cant be less than zero"));
	  }
	  

}
